#include "processor.h"

Processor::Processor(const char *name, long double relSpeed, const char *cpu_avail_trace, long double cpu_off_set, const char *cpu_avail_error, const char *cpu_avail_forecast) : Resource(name) {
	if ( ((cpu_avail_forecast != NULL) && FileChecker::verify(cpu_avail_forecast)) || FileChecker::verify(cpu_avail_trace) || FileChecker::verify(cpu_avail_error) )
		throw std::runtime_error("Cannot open cpu trace/forecast file");
	
	this->resource = SG_newHost(name, relSpeed, SG_SEQUENTIAL_IN_ORDER, cpu_avail_trace, cpu_off_set, 0, NULL, 0,0,NULL);

	this->cpu_avail_trace = new char[strlen(cpu_avail_trace)+1];
	this->cpu_avail_trace =  strcpy((char *)this->cpu_avail_trace, cpu_avail_trace);
	
	this->cpu_avail_error = new char[ strlen(cpu_avail_error)+1 ];
	this->cpu_avail_error = strcpy((char *)this->cpu_avail_error, cpu_avail_error);
	error_cpu = SG_newTrace(SG_SINGLE_LEVEL, SG_DYNAMIC, this->cpu_avail_error, 0.0, TRACE_TIMESTEP);
	
	this->cpu_avail_forecast = NULL;
	if (cpu_avail_forecast != NULL) {
		this->cpu_avail_forecast = new char[strlen(cpu_avail_forecast)+1];
		this->cpu_avail_forecast =  strcpy((char *)this->cpu_avail_forecast, cpu_avail_forecast);	
		forecast_cpu = SG_newTrace(SG_SINGLE_LEVEL, SG_DYNAMIC, this->cpu_avail_forecast,0.0,TRACE_TIMESTEP);
	}
	
	this->current_granularity = -1;
	this->mean_for_current_granularity = -1;

}

Processor::Processor(const char *name, long double relSpeed,  long double fixed_cpu) : Resource(name) {

	this->cpu_avail_forecast = NULL;
	this->cpu_avail_trace = NULL;

	this->resource = SG_newHost(name, relSpeed, SG_SEQUENTIAL_IN_ORDER, NULL, 0, fixed_cpu, NULL,0,0,NULL);
	
	this->current_granularity = -1;
	this->mean_for_current_granularity = -1;
	
}

Processor::~Processor() {

	if (this->cpu_avail_trace) delete this->cpu_avail_trace;
	if (this->cpu_avail_forecast) delete this->cpu_avail_forecast;	
	
//	if (forecast_cpu) free(forecast_cpu);
	
}

long double Processor::getCpuSpeed() {
	return SG_getHostRelSpeed(this->resource);
}

long double Processor::getCpuAvailable(long double time) {
	long double cpu_avail = SG_getHostLoad(this->resource, time);
	
	if ((!this->isPerformanceConstant()) && (this->cpu_avail_forecast!=NULL)) {
		if (time==-1) time = SG_getClock();

		cpu_avail = SG_getTraceValueWithOffset(forecast_cpu, time, this->getCpuOffset());		

	}
	
	return cpu_avail;
}

long double Processor::getCpuAvailableError(long double time) {
	long double cpu_error = SG_getTraceValueWithOffset( error_cpu, time, this->getCpuOffset() );
	return cpu_error;
}

const char *Processor::getCpuAvailableTrace() {
	return this->cpu_avail_trace;
}

const char *Processor::getCpuAvailableErrorTrace() {
	return this->cpu_avail_error;
}

const char *Processor::getCpuAvailableForecast() {
	return this->cpu_avail_forecast;
}

void Processor::setCpuOffset(long double new_offset) {
	this->resource->cpu_offset = new_offset;
}

long double Processor::getCpuOffset() {
	return this->resource->cpu_offset;
}

bool Processor::isBusy() {
	return (getNumberOfAllocatedTasks()>0);
}

int Processor:: getNumberOfAllocatedTasks() {

	return getNumberOfRunningTasks() + getNumberOfScheduledTasks();
	
}

int Processor::getNumberOfRunningTasks() {

	SG_Task *tasks_running = SG_getTasksRunningOnResource(this->getSGResource());	

	int n = 0;
	while (tasks_running[n]) {
		n++;
	}

	free(tasks_running);
	
	return n;
}

int Processor:: getNumberOfScheduledTasks() {

	SG_Task *tasks_sched = SG_getTasksScheduledOnResource(this->getSGResource());

	int n = 0;
	while (tasks_sched[n]) {
		n++;
	}
	
	free(tasks_sched);
	
	return n;
	
}
